home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n03 / ucrasm.exe / SOURCE.EXE / PRINTFF.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-11-08  |  16.8 KB  |  829 lines

  1. StdGrp        group    stdlib,stddata
  2. stddata        segment    para public 'sldata'
  3.         extrn    fpacc:word
  4. stddata        ends
  5. ;
  6. stdlib        segment    para public 'slcode'
  7.         assume    cs:stdgrp
  8. ;
  9.         extrn    sl_Putc:far, sl_Puti:far, sl_ISize:far
  10.         extrn    sl_Putw:far, sl_Puth:far
  11.         extrn    sl_Putu:far, sl_PutUL:far, sl_ULSize:far
  12.         extrn    sl_LSize:far, sl_USize:far, sl_PutL:far
  13.         extrn    sl_pute:far, sl_putf:far
  14.         extrn    sl_LSFPA:far, sl_LDFPA:far, sl_LEFPA:far
  15. ;
  16. ;
  17. putc        equ    sl_putc
  18. puti        equ    sl_puti
  19. ISize        equ    sl_ISize
  20. putw        equ    sl_putw
  21. puth        equ    sl_puth
  22. putu        equ    sl_putu
  23. putul        equ    sl_putul
  24. ulsize        equ    sl_ulsize
  25. lsize        equ    sl_lsize
  26. usize        equ    sl_usize
  27. putl        equ    sl_putl
  28. putf        equ    sl_putf
  29. pute        equ    sl_pute
  30. ;
  31. ;
  32. ; Printff- Like Printf except this guy supports floating point values too.
  33. ;       A program should not include both printf and printff.  Printff
  34. ;       includes everything printf does an more.  Including them both
  35. ;       would waste a lot of memory.  There are two routines because
  36. ;       most people don't need floating point I/O and printff links in
  37. ;       the floating point package which is quite large.
  38. ;
  39. ;               call    printf
  40. ;               db      "format string",0
  41. ;               dd      item1, item2, ..., itemn
  42. ;
  43. ; The format string is identical to "C".  Item1..Itemn are pointers to
  44. ; values to print for this string.  Each item must be matched by the
  45. ; corresponding "%xxx" item in the format string.
  46. ;
  47. ; Format string format:
  48. ;
  49. ; 1)    All characters, except the following, are printed to the standard
  50. ;       output as-is.
  51. ;
  52. ; 2)    "\" is the escape character.  Anything following it is printed
  53. ;       as-is except standard "C" values like \r, \n, \b, \t, etc.  If
  54. ;       a decimal digit follows the back-slash, printf assumes that this
  55. ;       is a hexadecimal number and converts following three digits to
  56. ;       an ASCII character and prints it.  Other back-slash operators are
  57. ;       just like those for "C".
  58. ;
  59. ; 3)    Format Control Strings:
  60. ;
  61. ;    General format:  "%s\cn^f" where:
  62. ;                s = -
  63. ;                n = a decimal integer or two integers
  64. ;                    separated by a period (for fp).
  65. ;                c = a fill character
  66. ;                ^ = ^
  67. ;                f = a format character
  68. ;
  69. ;            All fields except "%" and "f" are optional.
  70. ;
  71. ;    s = -       Left justify value and use fill character.
  72. ;    \c present    Use "c" as fill character.
  73. ;    n present    Use "n" as the minimum field width.
  74. ;    ^ present    The address associated with f is the address of a
  75. ;                pointer to the object, not the address of
  76. ;                the object itself.  The pointer is a far ptr.
  77. ;
  78. ;    f is one of the following
  79. ;
  80. ;        d -    Print signed integer in decimal notation.
  81. ;        i -    Print signed integer in decimal notation.
  82. ;        x -    Print word value in hexadecimal notation.
  83. ;        h -    Print byte value in hexadecimal notation.
  84. ;        u -    Print unsigned integer in decimal notation.
  85. ;        c -    Print character.
  86. ;        s -    Print string.
  87. ;        f -    Print floating point number in decimal form.
  88. ;         e -    Print floating point number in scientific notation.
  89. ;
  90. ;        ld-    Print long signed integer.
  91. ;        li-    Print long unsigned integer.
  92. ;        lx-    Print long hexadecimal number.
  93. ;        lu-    Print long unsigned number.
  94. ;        lf-    Print dbl prec fp number in decimal form.
  95. ;        le-    Print dbl prec fp number in scientific notation.
  96. ;
  97. ;        gf-    Print extended precision fp number in decimal form.
  98. ;        ge-    Print extended precision fp number in sci not form.
  99. ;
  100. ;
  101. ;    Calling Sequence:
  102. ;
  103. ;        call    Printf
  104. ;        db    "Format String",0
  105. ;        dd    adrs1, adrs2, ..., adrsn
  106. ;
  107. ;    Where the format string is ala "C" (and the descriptions above)
  108. ;    and adrs1..adrsn are addresses (far ptr) to the items to print.
  109. ;    Unless the "^" modifier is present, these addresses are the actual
  110. ;    addresses of the objects to print.
  111. ;
  112. ;
  113. ;
  114. cr        equ    0dh
  115. ff        equ    0ch
  116. lf        equ    0ah
  117. tab        equ    09h
  118. bs        equ    08h
  119. ;
  120. RtnAdrs        equ    2[bp]
  121. ;
  122.         public  sl_printff
  123. sl_printff    proc    far
  124.         push    bp
  125.         mov    bp, sp
  126.         pushf
  127.         push    ax
  128.         push    bx
  129.         push    cx
  130.         push    dx
  131.         push    di
  132.         push    si
  133.         push    es
  134.         push    ds
  135. ;
  136. ; Get pointers to the return address (format string).
  137.         cld
  138.         les    di, RtnAdrs
  139.         lds    si, RtnAdrs
  140. ;
  141. ; Okay, search for the end of the format string.  After these instructions,
  142. ; di points just beyond the zero byte at the end of the format string.  This,
  143. ; of course, points at the first address beyond the format string.
  144. ;
  145.         mov    al, 0
  146.         mov    cx, 65535
  147.     repne    scasb
  148. ;
  149. PrintItems:    lodsb            ;Get char si points at.
  150.         cmp    al, 0        ;EOS?
  151.         jz    PrintfDone
  152.         cmp    al, "%"        ;Start of a format string?
  153.         jz    FmtItem
  154.         cmp    al, "\"        ;Escape character?
  155.         jnz    PrintIt
  156.         call    GetEscChar
  157. PrintIt:    call    Putc
  158.         jmp    PrintItems
  159. ;
  160. FmtItem:    call    GetFmtItem    ;Process the format item here.
  161.         jmp    PrintItems
  162. ;
  163. PrintfDone:    mov    RtnAdrs, di    ;Put out new return address.
  164.         pop    ds
  165.         pop    es
  166.         pop    si
  167.         pop    di
  168.         pop    dx
  169.         pop    cx
  170.         pop    bx
  171.         pop    ax
  172.         pop    bp
  173.         popf
  174.         ret
  175. sl_printff      endp
  176. ;
  177. ;
  178. ;
  179. ;
  180. ; GetEscChar- Handles items immediately following the escape character "\".
  181. ;
  182. ;    Special escape characters (upper/lower case is acceptable):
  183. ;
  184. ;        n    Newline (cr/lf)
  185. ;        t    tab
  186. ;        b    backspace
  187. ;        r    return
  188. ;        l    line feed
  189. ;        f    formfeed
  190. ;        \    \
  191. ;        %    &
  192. ;        0xhh    Char with hex character code hh.  Must have exactly
  193. ;            two hexadecimal digits.
  194. ;
  195. GetEscChar    proc    near
  196.         lodsb            ;Get next character
  197.         cmp    al, 'n'
  198.         je    RtnNL
  199.         cmp    al, 'N'
  200.         je    RtnNL
  201.         cmp    al, 't'
  202.         je    RtnTab
  203.         cmp    al, 'T'
  204.         je    RtnTab
  205.         cmp    al, 'b'
  206.         je    RtnBS
  207.         cmp    al, 'B'
  208.         je    RtnBS
  209.         cmp    al, 'r'
  210.         je    RtnRtn
  211.         cmp    al, 'R'
  212.         je    RtnRtn
  213.         cmp    al, 'l'
  214.         je    RtnLF
  215.         cmp    al, 'L'
  216.         je    RtnLF
  217.         cmp    al, 'f'
  218.         je    RtnFF
  219.         cmp    al, 'F'
  220.         je    RtnFF
  221. ;
  222. ; Check for the presence of a 0xhh value here:
  223. ;
  224.         cmp    al, '0'
  225.         jne    RtnChar
  226.         cmp    byte ptr [si], 'x'
  227.         je    GetHex
  228.         cmp    byte ptr [si], 'X'
  229.         jne    RtnChar
  230. ;
  231. ; Okay, process the hex value here.  Note that exactly two hex digits must
  232. ; follow the 0x.
  233. ;
  234. GetHex:        inc    si        ;Point at first hex digit.
  235.         lodsb            ;Get first hex digit.
  236.         and    al, 05fh    ;l.c. -> u.c.
  237.         cmp    al, 'A'
  238.         jb    GotIt
  239.         sub    al, '7'
  240. GotIt:        shl    al, 1        ;Put into H.O. nibble.
  241.         shl    al, 1
  242.         shl    al, 1
  243.         shl    al, 1
  244.         mov    ah, al        ;Save for later
  245.         lodsb            ;Get next char.
  246.         and    al, 05fh
  247.         cmp    al, 'A'
  248.         jb    GotIt2
  249.         sub    al, '7'
  250. GotIt2:        and    al, 0fh
  251.         or    al, ah
  252.         ret            ;Return hex constant.
  253. ;
  254. ; RtnNL (return Newline) cheats.  It needs to return two characters.
  255. ; Since GetEscChar only returns a single character, this code goes ahead
  256. ; and calls putc to output the CR and the returns the LF.
  257. ;
  258. RtnNL:        mov    al, cr
  259.         call    Putc
  260.         mov    al, lf
  261.         ret
  262. ;
  263. RtnTab:        mov    al, tab
  264.         ret
  265. ;
  266. RtnBS:        mov    al, bs
  267.         ret
  268. ;
  269. RtnRtn:        mov    al, cr
  270.         ret
  271. ;
  272. RtnLF:        mov    al, lf
  273.         ret
  274. ;
  275. RtnFF:        mov    al, ff
  276. RtnChar:    ret
  277. ;
  278. GetEscChar    endp
  279. ;
  280. ;
  281. ;
  282. GetFmtItem    proc    near
  283.         lodsb                ;Get char beyond "%"
  284. ;
  285.         mov    cx, 1            ;Default field width is 1.
  286.         mov    dl, 0            ;Default is right justified
  287.         mov    dh, ' '            ;Default fill char is space.
  288.         mov    ah, ' '            ;Assume straight ptr, not handle.
  289. ;
  290. ; See if the user wants the value left justified:
  291. ;
  292.         cmp    al, '-'
  293.         jne    NotLeftJust
  294.         inc    dl            ;Set to right justified
  295.         lodsb                ;Get next character.
  296. ;
  297. ; See if the user wants to change the padding character.
  298. ;
  299. NotLeftJust:    cmp    al, '\'
  300.         jne    NoPadChange
  301.         lodsb                ;Get Padding Character.
  302.         mov    dh, al            ;Save padding character.
  303.         lodsb                ;Get next character
  304. ;
  305. ; See if the user wants a different field width:
  306. ;
  307. NoPadChange:    cmp    al, '0'
  308.         jb    NoFldWidth
  309.         cmp    al, '9'
  310.         ja    NoFldWidth
  311.         call    GetDecVal
  312. ;
  313. ; See if the user wants to specify a handle rather than a straight pointer
  314. ;
  315. NoFldWidth:    cmp    al, '^'
  316.         jne     ChkFmtChars
  317.         mov    ah, al
  318.         lodsb                ;Skip "^" character
  319. ;
  320. ; Okay, process the format characters down here.
  321. ;
  322. ChkFmtChars:    and    al, 05fh        ;l.c. -> U.C.
  323.         cmp    al, 'D'
  324.         je    PrintDec
  325.         cmp    al, 'I'
  326.         je    PrintDec
  327.         cmp    al, 'C'
  328.         je    PrintChar
  329. ;
  330.         cmp    al, 'X'
  331.         jne    TryH
  332.         jmp    PrintHexWord
  333. ;
  334. TryH:        cmp    al, 'H'
  335.         jne    TryU
  336.         jmp    PrintHexByte
  337. ;
  338. TryU:        cmp    al, 'U'
  339.         jne    TryString
  340.         jmp    PrintUDec
  341. ;
  342. TryString:    cmp    al, 'S'
  343.         jne    TryFloat
  344.         jmp    PrintString
  345. ;
  346. TryFloat:    cmp    al, 'F'
  347.         jne    TrySci
  348.         jmp    PrintSPFP
  349. ;
  350. TrySci:        cmp    al, 'E'
  351.         jne    TryExt
  352.         jmp    PrintSPFPE
  353. ;
  354. TryExt:        cmp    al, 'G'
  355.         jne    TryLong
  356.         lodsb            ;If it's the "G" modifier, look for F/E
  357.         and    al, 05fh    ;l.c. -> U.C.
  358.         cmp    al, 'F'        ;See if GF (ext prec., dec out).
  359.         jne    TryEE
  360.         jmp    PrintDPFP
  361. ;
  362. TryEE:        cmp    al, 'E'        ;See if GE (ext prec, sci not out).
  363.         jne    Default
  364.         jmp    PrintDPFPE
  365. ;
  366. ;
  367. ;
  368. TryLong:    cmp    al, 'L'
  369.         jne    Default
  370. ;
  371. ; If we've got the "L" modifier, this is a long value to print, get the
  372. ; data type character as the next value:
  373. ;
  374.         lodsb
  375.         and    al, 05fh        ;l.c. -> U.C.
  376.         cmp    al, 'D'
  377.         je    JmpDec
  378.         cmp    al, 'I'
  379.         jne    TryLU
  380. JmpDec:        jmp    LongDec
  381. ;
  382. TryLU:        cmp    al, 'U'
  383.         jne    TryX
  384.         jmp    LongU
  385. ;
  386. TryX:        cmp    al, 'X'
  387.         jne    TryLF
  388.         jmp    LongX
  389. ;
  390. TryLF:        cmp    al, 'F'
  391.         jne    TryLE
  392.         jmp     PrintEPFP
  393. ;
  394. TryLE:        cmp    al, 'E'
  395.         jne    Default
  396.         jmp    PrintEPFPE
  397. ;
  398. ;
  399. ; If none of the above, simply return without printing anything.
  400. ;
  401. Default:    ret
  402. ;
  403. ;
  404. ;
  405. PrintSPFP:      call    GetPtr
  406.         xchg    di, bx
  407.         call    sl_LSFPA
  408. DoTheRestf:    mov    ax, cx
  409.         call    putf
  410.         xchg    di, bx
  411.         ret
  412. ;
  413. PrintSPFPE:     call    GetPtr
  414.         xchg    di, bx
  415.         call    sl_LSFPA
  416. DoTheReste:    mov    ax, cx
  417.         call    pute
  418.         xchg    di, bx
  419.         ret
  420. ;
  421. PrintDPFP:    call    GetPtr
  422.         xchg    di, bx
  423.         call    sl_LDFPA
  424.         jmp    DoTheRestf
  425. ;
  426. PrintDPFPE:    call    GetPtr
  427.         xchg    di, bx
  428.         call    sl_LDFPA
  429.         jmp    DoTheReste
  430. ;
  431. PrintEPFP:    call    GetPtr
  432.         xchg    di, bx
  433.         call    sl_LEFPA
  434.         jmp    DoTheRestf
  435. ;
  436. PrintEPFPE:    call    GetPtr
  437.         xchg    di, bx
  438.         call    sl_LEFPA
  439.         jmp    DoTheReste
  440. ;
  441. ;
  442. ;
  443. ; Print a signed decimal value here.
  444. ;
  445. PrintDec:    call    GetPtr            ;Get next pointer into ES:BX
  446.         mov    ax, es:[bx]        ;Get value to print.
  447.         call    ISize            ;Get the size of this guy.
  448.         sub    al, cl            ;Compute padding size
  449.         neg    al
  450.         cbw
  451.         mov    cx, ax
  452.         mov    ax, es:[bx]        ;Retrieve value to print.
  453.         js    NoPadDec        ;Is CX negative?
  454.         cmp    dl, 0            ;Right justified?
  455.         jne    LeftJustDec
  456.         call    PrintPad        ;Print padding characters
  457.         call    Puti            ;Print the integer
  458.         ret                ;We're done!
  459. ;
  460. ; Print left justified value here.
  461. ;
  462. LeftJustDec:    call    Puti
  463.         call    PrintPad
  464.         ret
  465. ;
  466. ; Print non-justified value here:
  467. ;
  468. NoPadDec:    call    Puti
  469.         ret
  470. ;
  471. ;
  472. ;
  473. ; Print a character variable here.
  474. ;
  475. PrintChar:    call    GetPtr            ;Get next pointer into ES:BX
  476.         mov    al, es:[bx]        ;Retrieve value to print.
  477.         mov    ch, 0
  478.         dec    cx
  479.         js    NoPadChar        ;Is CX negative?
  480.         cmp    dl, 0            ;Right justified?
  481.         jne    LeftJustChar
  482.         call    PrintPad        ;Print padding characters
  483.         call    Putc            ;Print the character
  484.         ret                ;We're done!
  485. ;
  486. ; Print left justified value here.
  487. ;
  488. LeftJustChar:    call    Putc
  489.         call    PrintPad
  490.         ret
  491. ;
  492. ; Print non-justified character here:
  493. ;
  494. NoPadChar:    call    Putc
  495.         ret
  496. ;
  497. ;
  498. ;
  499. ;
  500. ; Print a hexadecimal word value here.
  501. ;
  502. PrintHexWord:    call    GetPtr            ;Get next pointer into ES:BX
  503.         mov    ax, es:[bx]        ;Get value to print.
  504.         mov    ch, 0
  505.         sub    cx, 4            ;Compute padding
  506.         js    NoPadHexW        ;Is CX negative?
  507.         cmp    dl, 0            ;Right justified?
  508.         jne    LeftJustHexW
  509.         call    PrintPad        ;Print padding characters
  510.         call    Putw            ;Print the hex value
  511.         ret                ;We're done!
  512. ;
  513. ; Print left justified value here.
  514. ;
  515. LeftJustHexW:    call    Putw
  516.         call    PrintPad
  517.         ret
  518. ;
  519. ; Print non-justified value here:
  520. ;
  521. NoPadHexW:    call    Putw
  522.         ret
  523. ;
  524. ;
  525. ;
  526. ;
  527. ; Print hex bytes here.
  528. ;
  529. ;
  530. PrintHexByte:    call    GetPtr            ;Get next pointer into ES:BX
  531.         mov    ax, es:[bx]        ;Get value to print.
  532.         mov    ch, 0
  533.         sub    cx, 2            ;Compute padding
  534.         js    NoPadHexB        ;Is CX negative?
  535.         cmp    dl, 0            ;Right justified?
  536.         jne    LeftJustHexB
  537.         call    PrintPad        ;Print padding characters
  538.         call    Puth            ;Print the hex value
  539.         ret                ;We're done!
  540. ;
  541. ; Print left justified value here.
  542. ;
  543. LeftJustHexB:    call    Puth
  544.         call    PrintPad
  545.         ret
  546. ;
  547. ; Print non-justified value here:
  548. ;
  549. NoPadHexB:    call    Puth
  550.         ret
  551. ;
  552. ;
  553. ;
  554. ; Output unsigned decimal numbers here:
  555. ;
  556. PrintUDec:    call    GetPtr            ;Get next pointer into ES:BX
  557.         mov    ax, es:[bx]        ;Get value to print.
  558.         call    USize            ;Get the size of this guy.
  559.         mov    ch, 0
  560.         sub    cx, ax                 ;Compute padding
  561.         mov    ax, es:[bx]        ;Retrieve value to print.
  562.         js    NoPadUDec        ;Is CX negative?
  563.         cmp    dl, 0            ;Right justified?
  564.         jne    LeftJustUDec
  565.         call    PrintPad        ;Print padding characters
  566.         call    Putu            ;Print the integer
  567.         ret                ;We're done!
  568. ;
  569. ; Print left justified value here.
  570. ;
  571. LeftJustUDec:    call    Putu
  572.         call    PrintPad
  573.         ret
  574. ;
  575. ; Print non-justified value here:
  576. ;
  577. NoPadUDec:    call    Putu
  578.         ret
  579. ;
  580. ;
  581. ;
  582. ;
  583. ; Output a string here:
  584. ;
  585. PrintString:    call    GetPtr            ;Get next pointer into ES:BX
  586. ;
  587. ; Compute the length of the string:
  588. ;
  589.         push    di
  590.         push    cx
  591.         mov    cx, -1
  592.         mov    di, bx
  593.         mov    al, 0
  594.     repne    scasb
  595.         mov    ax, cx
  596.         neg    ax
  597.         dec    ax
  598.         dec    ax
  599.         pop    cx
  600.         pop    di
  601.         mov    ch, 0
  602.         sub    cx, ax            ;Field width - String Length.
  603. ;
  604.         js    NoPadStr        ;Is CX negative?
  605.         cmp    dl, 0            ;Right justified?
  606.         jne    LeftJustStr
  607.         call    PrintPad        ;Print padding characters
  608.         call    Puts            ;Print the string
  609.         ret                ;We're done!
  610. ;
  611. ; Print left justified value here.
  612. ;
  613. LeftJustStr:    call    Puts
  614.         call    PrintPad
  615.         ret
  616. ;
  617. ; Print non-justified value here:
  618. ;
  619. NoPadStr:    call    Puts
  620.         ret
  621. GetFmtItem    endp
  622. ;
  623. ;
  624. ;
  625. ; Print a signed long decimal value here.
  626. ;
  627. LongDec:    call    GetPtr            ;Get next pointer into ES:BX
  628.         mov    ax, es:[bx]        ;Get value to print.
  629.         push    dx
  630.         mov    dx, es:2[bx]
  631.         call    LSize            ;Get the size of this guy.
  632.         pop    dx
  633.         mov    ch, 0
  634.         sub    cx, ax                 ;Compute padding
  635.         mov    ax, es:[bx]        ;Retrieve value to print.
  636.         js    NoPadLong        ;Is CX negative?
  637.         cmp    dl, 0            ;Right justified?
  638.         jne    LeftJustLong
  639.         call    PrintPad        ;Print padding characters
  640.         mov    dx, es:2[bx]        ;Get H.O. word
  641.         call    PutL            ;Print the integer
  642.         ret                ;We're done!
  643. ;
  644. ; Print left justified value here.
  645. ;
  646. LeftJustLong:    push    dx
  647.         mov    dx, es:2[bx]        ;Get H.O. word
  648.         call    PutL
  649.         pop    dx
  650.         call    PrintPad
  651.         ret
  652. ;
  653. ; Print non-justified value here:
  654. ;
  655. NoPadLong:    mov    dx, es:2[bx]        ;Get H.O. word
  656.         call    Putl
  657.         ret
  658. ;
  659. ;
  660. ; Print an unsigned long decimal value here.
  661. ;
  662. LongU:        call    GetPtr            ;Get next pointer into ES:BX
  663.         mov    ax, es:[bx]        ;Get value to print.
  664.         push    dx
  665.         mov    dx, es:[bx]
  666.         call    ULSize            ;Get the size of this guy.
  667.         pop    dx
  668.         mov    ch, 0
  669.         sub    cx, ax                 ;Compute padding
  670.         mov    ax, es:[bx]        ;Retrieve value to print.
  671.         js    NoPadULong        ;Is CX negative?
  672.         cmp    dl, 0            ;Right justified?
  673.         jne    LeftJustULong
  674.         call    PrintPad        ;Print padding characters
  675.         mov    dx, es:2[bx]        ;Get H.O. word
  676.         call    PutUL            ;Print the integer
  677.         ret                ;We're done!
  678. ;
  679. ; Print left justified value here.
  680. ;
  681. LeftJustULong:    push    dx
  682.         mov    dx, es:2[bx]        ;Get H.O. word
  683.         call    PutUL
  684.         pop    dx
  685.         call    PrintPad
  686.         ret
  687. ;
  688. ; Print non-justified value here:
  689. ;
  690. NoPadULong:    mov    dx, es:2[bx]        ;Get H.O. word
  691.         call    Putul
  692.         ret
  693. ;
  694. ;
  695. ; Print a long hexadecimal value here.
  696. ;
  697. LongX:        call    GetPtr            ;Get next pointer into ES:BX
  698.         mov    ch, 0
  699.         sub    cx, 8            ;Compute padding
  700.         js    NoPadXLong        ;Is CX negative?
  701.         cmp    dl, 0            ;Right justified?
  702.         jne    LeftJustXLong
  703.         call    PrintPad        ;Print padding characters
  704.         mov    ax, es:2[bx]        ;Get H.O. word
  705.         call    Putw
  706.         mov    ax, es:[bx]
  707.         call    Putw
  708.         ret                ;We're done!
  709. ;
  710. ; Print left justified value here.
  711. ;
  712. LeftJustxLong:    mov    ax, es:2[bx]        ;Get H.O. word
  713.         call    Putw
  714.         mov    ax, es:[bx]        ;Get L.O. word
  715.         call    Putw
  716.         call    PrintPad
  717.         ret
  718. ;
  719. ; Print non-justified value here:
  720. ;
  721. NoPadxLong:    mov    ax, es:2[bx]        ;Get H.O. word
  722.         call    Putw
  723.         mov    ax, es:[bx]
  724.         call    Putw
  725.         ret
  726. ;
  727. ;
  728. ;
  729. ;
  730. ; Puts- Outputs the zero terminated string pointed at by ES:BX.
  731. ;
  732. Puts        proc    near
  733. PutsLp:        mov    al, es:[bx]
  734.         cmp    al, 0
  735.         je    PutsDone
  736.         call    putc
  737.         inc    bx
  738.         jmp    PutsLp
  739. ;
  740. PutsDone:    ret
  741. Puts        endp
  742. ;
  743. ;
  744. ;
  745. ;
  746. ;
  747. ; PrintPad-    Prints padding characters.  Character to print is in DH.
  748. ;        We must print it CX times.  CX must be greater than zero.
  749. ;
  750. PrintPad    proc    near
  751.         push    ax
  752.         mov    al, dh
  753.         jcxz    NoPadding
  754. PPLoop:        call    Putc
  755.         loop    PPLoop
  756. NoPadding:    pop    ax
  757.         ret
  758. PrintPad    endp
  759. ;
  760. ;
  761. ;
  762. ;
  763. ;
  764. ; GetPtr- Grabs the next pointer which DS:DI points at and returns this
  765. ;      far pointer in ES:BX.
  766. ;
  767. GetPtr        proc    near
  768.         les    bx, [di]
  769.         add    di, 4
  770. ;
  771. ; See if this is a handle rather than a pointer.
  772. ;
  773.         cmp    ah, '^'
  774.         jne    NotHandle
  775.         les    bx, es:[bx]
  776. NotHandle:    ret
  777. GetPtr        endp
  778. ;
  779. ;
  780. ;
  781. ;
  782. ;
  783. ; GetDecVal-    Converts the string of decimal digits in AL and [SI] into
  784. ;        an integer and returns this integer in CL/CH.
  785. ;
  786. GetDecVal    proc    near
  787.         push    dx
  788.         dec    si
  789.         xor    cx, cx
  790. DecLoop:    lodsb
  791.         cmp    al, '0'
  792.         jb    NoMore
  793.         cmp    al, '9'
  794.         ja    NoMore
  795.         and    al, 0fh
  796.         shl    cl, 1            ;Compute CL := CL*10 + al
  797.         mov    dl, cl
  798.         shl    cl, 1
  799.         shl    cl, 1
  800.         add    cl, dl
  801.         add    cl, al
  802.         jmp    DecLoop
  803. ;
  804. NoMore:        cmp    al, '.'
  805.         jne    ReallyNoMore
  806. ;
  807. ; User entered nnn.nnn here.  Process for floating point values:
  808. ;
  809. DecLoop2:    lodsb
  810.         cmp    al, '0'
  811.         jb    ReallyNoMore
  812.         cmp    al, '9'
  813.         ja    ReallyNoMore
  814.         and    al, 0fh
  815.         shl    ch, 1            ;Compute CX := CX*10 + al
  816.         mov    dh, ch
  817.         shl    ch, 1
  818.         shl    ch, 1
  819.         add    ch, dh
  820.         add    ch, al
  821.         jmp    DecLoop2
  822. ;
  823. ReallyNoMore:    pop    dx
  824.         ret
  825. GetDecVal    endp
  826. ;
  827. stdlib        ends
  828.         end
  829.